﻿
function MandelbrotPainter(canvas)
{
  var _canvas = canvas;
  var _transform;
  var _doneHandler;

  var _order;
  var _workQueue;

  this.paint = function(transform, done)
  {
    this.stop();

    _transform = transform;
    _doneHandler = done;
    _order = new PixelOrder(_canvas.width, _canvas.height);
    _workQueue = new EscapeTimeQueue()

    startPixel();
  };

  this.stop = function()
  {
    endPaint(false);
  };

  function startPixel()
  {
    var pixel = _order.pixel;
    var size = _order.stride;
    var point = _transform(
      [pixel[0] + 0.5 * size, pixel[1] + 0.5 * size]);
    _workQueue.addPoint(point,
      function(potential)
      {
        drawPixel(pixel, size, getColor(potential));
        startNextPixel();
      });
  }

  function endPaint(complete)
  {
    if(_doneHandler && _doneHandler instanceof Function)
      _doneHandler(complete);

    if(_workQueue)
      _workQueue.finalize();

    _transform = null;
    _doneHandler = null;
    _order = null;
    _workQueue = null;
  }

  function startNextPixel()
  {
    if(_order.next())
      startPixel();
    else
      endPaint(true);
  }

  function drawPixel(pixel, size, color)
  {
    var context = canvas.getContext('2d');
    context.save();
    context.fillStyle = color;
    context.fillRect(pixel[0], pixel[1], size, size);
    context.restore();
  }

  function getColor(potential)
  {
    if(potential == 0)
      return 'black';

    var shade = potential;
    var c1, c2;
    if(shade <= 3/4) {
      shade *= 4/3;
      c1 = [0, 0, 0]
      c2 = [ 1, 165 / 255, 0 ];
    }
    else
    {
      shade = shade * 4 - 3;
      c1 = [ 1, 165 / 255, 0 ];
      c2 = [0, 0, 128 / 255];
    }
    var color = c1.map(function(c, i) { return c + (c2[i] - c) * shade; });
    return 'rgb(' + (color[0] * 100) + '%,' + (color[1] * 100) + '%,' + (color[2] * 100) + '%)';
  }

  return this;
}
MandelbrotPainter.prototype = new Object();
MandelbrotPainter.prototype.constructor = MandelbrotPainter;
